package io.xxx.eva.robot;

import com.alibaba.fastjson.JSON;
import io.xxx.eva.receiver.Receiver;
import io.xxx.eva.robot.send.IPadSender;
import io.xxx.eva.robot.send.PhoneSender;
import io.xxx.eva.robot.send.limit.MessageLimiter;
import io.xxx.eva.task.Task;
import io.xxx.eva.task.TaskMessage;
import jakarta.annotation.Nonnull;
import jakarta.annotation.PreDestroy;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Triple;
import org.redisson.api.RRateLimiter;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadLocalRandom;

@Slf4j
@AllArgsConstructor
public class Talker implements Runnable {

    private final ArrayBlockingQueue<Triple<Task, Receiver, List<TaskMessage>>> queue = new ArrayBlockingQueue<>(1_000);

    private RRateLimiter speedRateLimiter;

    private List<MessageLimiter> limiters;

    private IPadSender iPadSender;

    private PhoneSender phoneSender;

    private volatile boolean running;

    private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();

    @SneakyThrows
    public void say(Task task, Receiver receiver, List<TaskMessage> messages) {
        queue.put(Triple.of(task, receiver, messages));
    }


    @Override
    public void run() {
        while (running()) {
            Triple<Task, Receiver, List<TaskMessage>> triple = next();
            Task task = triple.getLeft();
            Receiver receiver = triple.getMiddle();
            Robot robot = chooseRobot(receiver);
            List<TaskMessage> messages = triple.getRight();
            for (TaskMessage message : messages) {
                for (MessageLimiter limiter : limiters) {
                    limiter.acquire(robot, message);
                }
                speedRateLimiter.acquire();
                switch (task.getSendMode()) {
                    case IPAD -> iPadSender.send(receiver, message);
                    case PHONE -> phoneSender.send(receiver, message);
                }
                log.info("消息发送完成[task:{},receiver:{},message:{}]",
                        JSON.toJSONString(task), JSON.toJSONString(receiver), JSON.toJSONString(message));
            }
        }
    }

    @SneakyThrows
    @Nonnull
    private Triple<Task, Receiver, List<TaskMessage>> next() {
        return queue.take();
    }

    private Robot chooseRobot(@Nonnull Receiver receiver) {
        List<Robot> robots = receiver.robots();
        int i = RANDOM.nextInt(0, robots.size());
        return robots.get(i);
    }

    private boolean running() {
        return running;
    }

    @PreDestroy
    public void stop() {
        this.running = false;
    }
}
